home *** CD-ROM | disk | FTP | other *** search
/ User's Choice Windows CD / User's Choice Windows CD (CMS Software)(1993).iso / utility3 / huge2.zip / HUGEARR.C < prev    next >
Text File  |  1992-02-23  |  21KB  |  513 lines

  1. /************************************************************************
  2. *                                                                       *
  3. *                               HUGEARR.DLL                             *
  4. *                                                                       *
  5. *               Huge array support for Microsoft Visual Basic           *
  6. *                                                                       *
  7. *                             By Mike Warning                           *
  8. *                                                                       *
  9. *                          HugeSave and HugeLoad                        *
  10. *                                                                       *
  11. *            By Harry JF Wykes - End User Computing Limited             *
  12. *                                                                       *
  13. ************************************************************************/
  14.  
  15. #include <memory.h>
  16. #include <windows.h>
  17. #include "hugearr.h"
  18.  
  19. HANDLE                  hLocalMem;              // handle to local memory
  20. int                     NumArrays;              // total number of arrays
  21.  
  22. /************************************************************************
  23. * LibMain -                                                             *
  24. *   Standard DLL constructor.  Allocates all of local heap to store     *
  25. * array descriptors and then set the total number of arrays possible.   *
  26. ************************************************************************/
  27. int FAR pascal
  28.      LibMain(HANDLE hModule, WORD wDataSeg, WORD cbHeapSize, LPSTR lpszCmdLine)
  29. {
  30.     if (cbHeapSize > 0)
  31.         UnlockData(0);
  32.                                         // Allocate memory for array descrips.
  33.     hLocalMem = LocalAlloc(LMEM_MOVEABLE | LMEM_ZEROINIT,
  34.                                              LocalCompact((WORD) 65500));
  35.     if (hLocalMem == NULL)
  36.         return 0;                       // Something happened, bomb out
  37.                                         // calc total number of arrays
  38.     NumArrays = (int) (LocalSize(hLocalMem) / sizeof(struct ArrayDesc));
  39.     return (1);
  40. }
  41.  
  42. /************************************************************************
  43. * WEP -                                                                 *
  44. *   Standard DLL destructor.  Free up local memory and quit.            *
  45. ************************************************************************/
  46. int FAR pascal WEP(int bSystemExit)
  47. {
  48.     LocalFree(hLocalMem);
  49.     return (1);
  50. }
  51.  
  52. /************************************************************************
  53. * HugeDim -                                                             *
  54. *   Dimensions a new array.  The size of the array is                   *
  55. * (recsize * ubound+1). Recsize is the size in bytes of each element in *
  56. * the array and ubound is the upper bound of the array. All arrays have *
  57. * a lower bound of 0.                                                   *
  58. *                                                                       *
  59. * Note: If total size of the array is greater than 64k, recsize should  *
  60. *       be an integer power of two (1,2,4,8,16,etc.)  Otherwise, the    *
  61. *       huge pointers will not be added correctly.                      *
  62. ************************************************************************/
  63. int FAR pascal HugeDim(int recsize, long ubound)
  64. {
  65.     int         hArray;                 // handle to array to dimension
  66.     pDescrip    pArray;                 // pointer to array descriptor
  67.     int         ret;                    // return value from HugeAlloc
  68.  
  69.     pArray = (pDescrip) LocalLock(hLocalMem);   // find a free array
  70.     if ((hArray = GetFreeArray(pArray)) == HA_TOMANYARRAYS)  {
  71.         LocalUnlock(hLocalMem);                 // couldn't find one,
  72.         return (HA_TOMANYARRAYS);               // return error.
  73.     }
  74.                                         // allocate new array
  75.     ret = HugeAlloc(pArray + hArray, recsize, ubound, FALSE);
  76.     LocalUnlock(hLocalMem);
  77.  
  78.     if (ret < 0)                        // if an error occured during alloc
  79.         return (ret);                   // return the error, else
  80.     else
  81.         return (hArray);                // return the handle to the array
  82.  
  83. }
  84.  
  85. /************************************************************************
  86. * HugeRedim -                                                           *
  87. *   Redimenions the given array to have the new 'ubound'.  The old      *
  88. * recsize is kept.  All data in the array is preserved and any new data *
  89. * (created by expanding the array) is initialized to 0.                 *
  90. *                                                                       *
  91. * Note: The recsize must be an integer power of two if the total array  *
  92. *       size is greater than 64k.                                       *
  93. ************************************************************************/
  94. int FAR pascal HugeRedim(int hArray, long ubound)
  95. {
  96.     pDescrip    pArray;                 // pointer to array desciptor
  97.     register    ret;                    // return code of HugeAlloc
  98.  
  99.     if (hArray < 0 | hArray >= NumArrays)
  100.         return (HA_BADARRAY);           // illegal array handle
  101.  
  102.     pArray = (pDescrip) LocalLock(hLocalMem) + hArray;
  103.  
  104.     if (pArray -> handle != NULL)       // reallocate array
  105.         ret = HugeAlloc(pArray, pArray -> recsize, ubound, TRUE);
  106.     else
  107.         ret = HA_BADARRAY;              // array has never been allocated
  108.  
  109.     LocalUnlock(hLocalMem);
  110.     return (ret);
  111. }
  112.  
  113.  
  114. /********************************************************************
  115. * GetFreeArray -                                                    *
  116. *   Searches the array descriptor table looking for a free entry.   *
  117. * It returns the index into the table if an entry is free or        *
  118. * HA_TOMANYARRAYS otherwise.  pArray is the pointer to the start of *
  119. * the table.                                                        *
  120. ********************************************************************/
  121. int GetFreeArray(pDescrip pArray)
  122. {
  123.     int i = 0;
  124.                                         // loop until found or out of entries
  125.     while ((i < NumArrays) && (pArray -> handle != NULL))  {
  126.         ++pArray;
  127.         ++i;
  128.     }
  129.  
  130.     if (i == NumArrays)                 // didn't find a spot
  131.         return (HA_TOMANYARRAYS);
  132.  
  133.     return (i);                         // found one, return index to it
  134. }
  135.  
  136. /********************************************************************
  137. * GetHugeEl -                                                       *
  138. *   Retrieves an element of the array storing it into the buffer    *
  139. * pointed to by 'buffer'.  hArray is the index into the descriptor  *
  140. * table of the array, element is the element to get.                *
  141. *                                                                   *
  142. * NOTE: there is absolutely no type checking done on the buffer.    *
  143. *       It is up to the programmer to make sure it points to the    *
  144. *       correct data type.                                          *
  145. ********************************************************************/
  146. int FAR pascal GetHugeEl(int hArray, long element, BYTE FAR *buffer)
  147. {
  148.     BYTE _huge          *ptr;               // pointer to array element
  149.     pDescrip            pArray;             // pointer to array descriptor
  150.  
  151.     if (hArray < 0 || hArray >= NumArrays)
  152.         return (HA_BADARRAY);               // illegal array handle
  153.  
  154.                                             // point to proper descriptor
  155.     pArray = (pDescrip) LocalLock(hLocalMem) + hArray;
  156.  
  157.     if (pArray -> handle == NULL)  {
  158.         LocalUnlock(hLocalMem);
  159.         return (HA_BADARRAY);               // array hasn't been allocated
  160.     }
  161.     if ((pArray -> ubound < element) || (element < 0))  {
  162.         LocalUnlock(hLocalMem);
  163.         return (HA_SUBSCRIPT);              // subscript out of range
  164.     }
  165.                                             // calculate pointer to element
  166.     ptr = (BYTE _huge *) GlobalLock(pArray -> handle);
  167.     ptr = ptr + element * pArray->recsize;
  168.     _fmemcpy(buffer, ptr, pArray -> recsize);   // copy data
  169.  
  170.     GlobalUnlock(pArray -> handle);
  171.     LocalUnlock(hLocalMem);
  172.     return (HA_OK);
  173. }
  174.  
  175. /********************************************************************
  176. * SetHugeEl -                                                       *
  177. *   Sets the value of an array element.  This routine is exactly    *
  178. * the same as 'GetHugeEl' except that the memory copy is resversed. *
  179. ********************************************************************/
  180. int FAR pascal SetHugeEl(int hArray, long element, BYTE FAR *buffer)
  181. {
  182.     BYTE _huge          *ptr;               // pointer to array element
  183.     pDescrip            pArray;             // pointer to array descriptor
  184.  
  185.     if (hArray < 0 || hArray >= NumArrays)
  186.         return (HA_BADARRAY);               // illegal array handle
  187.  
  188.                                             // point to proper descriptor
  189.     pArray = (pDescrip) LocalLock(hLocalMem) + hArray;
  190.  
  191.     if (pArray -> handle == NULL)  {
  192.         LocalUnlock(hLocalMem);
  193.         return (HA_BADARRAY);               // array hasn't been allocated
  194.     }
  195.     if ((pArray -> ubound < element) || (element < 0))  {
  196.         LocalUnlock(hLocalMem);
  197.         return (HA_SUBSCRIPT);              // subscript out of range
  198.     }
  199.                                             // calculate pointer to element
  200.     ptr = (BYTE _huge *) GlobalLock(pArray -> handle);
  201.     ptr = ptr + element * pArray->recsize;
  202.     _fmemcpy(ptr, buffer, pArray -> recsize);   // copy data
  203.  
  204.     GlobalUnlock(pArray -> handle);
  205.     LocalUnlock(hLocalMem);
  206.     return (HA_OK);
  207. }
  208.  
  209. /********************************************************************
  210. * HugeErase -                                                       *
  211. *   Deletes an array and marks it as free in the descriptor table.  *
  212. * 'hArray' is the array to erase.                                   *
  213. ********************************************************************/
  214. int FAR pascal HugeErase(int hArray)
  215. {
  216.     pDescrip    pArray;                     // pointer to array descriptor
  217.  
  218.     if (hArray < 0 || hArray >= NumArrays)
  219.         return (HA_BADARRAY);               // illegal array handle
  220.  
  221.     pArray = (pDescrip) LocalLock(hLocalMem) + hArray;
  222.     if (pArray -> handle == NULL)  {
  223.         LocalUnlock(hLocalMem);
  224.         return (HA_BADARRAY);               // array hasn't been allocated yet
  225.     }
  226.  
  227.     GlobalFree(pArray -> handle);           // free the memory
  228.     pArray -> handle = NULL;
  229.  
  230.     LocalUnlock(hLocalMem);
  231.     return (HA_OK);
  232. }
  233.  
  234. /********************************************************************
  235. * NumHugeArrays -                                                   *
  236. *   Returns the number of free entries in the array descriptor table*
  237. ********************************************************************/
  238. int FAR pascal NumHugeArrays(void)
  239. {
  240.     pDescrip            pArray;             // pointer to current descriptor
  241.     int                 num, i;             // number free so far
  242.  
  243.     pArray = (pDescrip) LocalLock(hLocalMem);
  244.     for (i = 0, num = 0; i < NumArrays; i++, pArray++)
  245.         if (pArray -> handle == NULL)
  246.             ++num;
  247.  
  248.     LocalUnlock(hLocalMem);
  249.     return (num);
  250. }
  251.  
  252.  
  253. /********************************************************************
  254. * HugeUbound -                                                      *
  255. *   Returns the upper bound of a given array                        *
  256. ********************************************************************/
  257. long FAR pascal HugeUbound(int hArray)
  258. {
  259.     pDescrip    pArray;                     // pointer to array descriptor
  260.     long    ubound;                     // upper bound of array
  261.  
  262.     if (hArray < 0 || hArray >= NumArrays)
  263.         return (HA_BADARRAY);               // illegal array handle
  264.  
  265.     pArray = (pDescrip) LocalLock(hLocalMem) + hArray;
  266.     if (pArray -> handle == NULL)  {
  267.         LocalUnlock(hLocalMem);
  268.         return (HA_BADARRAY);               // array hasn't been allocated yet
  269.     }
  270.  
  271.     ubound = pArray -> ubound;
  272.     LocalUnlock(hLocalMem);
  273.  
  274.     return (ubound);
  275. }
  276.  
  277.  
  278. /********************************************************************
  279. * HugeInt -                                                         *
  280. *   Same as GetHugeEl except that it explicitly returns an integer. *
  281. * Use this function when you are in an expression such as:          *
  282. *           i% = 5 * HugeInt(4, 5)                                  *
  283. *                                                                   *
  284. * NOTE: Because the user could store anything in the array element, *
  285. *       they will not know if the value returned is a real value or *
  286. *       if an error occured.  Use GetHugeEl if the error code must  *
  287. *       be checked.                                                 *
  288. ********************************************************************/
  289. int FAR pascal HugeInt(int hArray, long element)
  290. {
  291.     int     retval;
  292.  
  293.     GetHugeEl(hArray, element, (BYTE FAR *) &retval);
  294.     return (retval);
  295. }
  296.  
  297.  
  298. /********************************************************************
  299. * HugeLong -                                                        *
  300. *   Returns an element of a long integer array.  (re. HugeInt)      *
  301. ********************************************************************/
  302. long FAR pascal HugeLong(int hArray, long element)
  303. {
  304.     long    retval;
  305.  
  306.     GetHugeEl(hArray, element, (BYTE FAR *) &retval);
  307.     return (retval);
  308. }
  309.  
  310.  
  311.  
  312. /********************************************************************
  313. * HugeSingle -                                                      *
  314. *   Returns an element of a single precesion array.  (re. HugeInt)  *
  315. ********************************************************************/
  316. float FAR pascal HugeSingle(int hArray, long element)
  317. {
  318.     float  retval;
  319.  
  320.     GetHugeEl(hArray, element, (BYTE FAR *) &retval);
  321.     return (retval);
  322. }
  323.  
  324.  
  325. /********************************************************************
  326. * HugeDouble -                                                      *
  327. *   Returns an element of a double precesion array.  (re. HugeInt)  *
  328. ********************************************************************/
  329. double FAR pascal HugeDouble(int hArray, long element)
  330. {
  331.     double  retval;
  332.  
  333.     GetHugeEl(hArray, element, (BYTE FAR *) &retval);
  334.     return (retval);
  335. }
  336.  
  337.  
  338. /********************************************************************
  339. * HugeCurrency -                                                    *
  340. *   Returns an element of a currency array.  (re. HugeInt)          *
  341. ********************************************************************/
  342. currency FAR pascal HugeCurrency(int hArray, long element)
  343. {
  344.     return((currency) HugeDouble(hArray, element));
  345. }
  346.  
  347. /********************************************************************
  348. *   HugeAlloc -                                                     *
  349. * Allocates (or reallocates) global memory for an array.  The size  *
  350. * of the array is recsize * (ubound + 1) bytes.  The information    *
  351. * for the array is stored in the array descriptor pointed to by     *
  352. * 'pArray'.                                                         *
  353. *                                                                   *
  354. * Note:  See HugeDim for a discussion on array size limitations.    *
  355. ********************************************************************/
  356. int HugeAlloc(pDescrip pArray,int recsize,long ubound, BOOL realloc)
  357. {
  358.     HANDLE              handle;             // temp handle for alloc
  359.  
  360.     ++ubound;                               // ubound = #elements - 1
  361.     if (recsize * ubound > 0xffff)          // is size integer power two?
  362.         if ((recsize <= 0) || (((recsize - 1) & recsize) != 0))
  363.             return (HA_BADELEMENTSIZE);
  364.  
  365.     if (realloc)                            // allocate array
  366.         handle = GlobalReAlloc(pArray -> handle, recsize * ubound,
  367.                                                GMEM_MOVEABLE || GMEM_ZEROINIT);
  368.     else
  369.         handle = GlobalAlloc(GMEM_MOVEABLE || GMEM_ZEROINIT, recsize * ubound);
  370.  
  371.     if (handle == NULL)
  372.         return (HA_OUTOFMEMORY);            // out of memory
  373.  
  374.     pArray -> handle = handle;              // save new handle
  375.     pArray -> recsize = recsize;            // record element size
  376.     pArray -> ubound = ubound - 1;
  377.  
  378.     return (HA_OK);
  379. }
  380.  
  381. /********************************************************************
  382. *   HugeSave - Saves the specified number of elements to a file     *
  383. *              Returns the number of items saved.                   *
  384. *                                                                   *
  385. *   NB!   HugeSave does not Erase the Huge Array.                   *
  386. ********************************************************************/
  387. long FAR pascal HugeSave(int hArray, long nelements, int OutLen, LPSTR FileSpec)
  388.  {
  389.    int                 hSaveFile;          // handle to the save file
  390.    BYTE _huge          *ptr;               // pointer to array element
  391.    long                element;            // element in the huge array
  392.    pDescrip            pArray;             // pointer to array descriptor
  393.  
  394.    if (hArray < 0 || hArray >= NumArrays)
  395.        return (HA_BADARRAY);               // illegal array handle
  396.  
  397.    pArray = (pDescrip) LocalLock(hLocalMem) + hArray;
  398.  
  399.    if (pArray -> handle == NULL)
  400.     {
  401.        LocalUnlock(hLocalMem);
  402.        return (HA_BADARRAY);               // array hasn't been allocated yet
  403.     }
  404.  
  405.     if ((pArray -> ubound < nelements) || (nelements < 0))
  406.      {
  407.         LocalUnlock(hLocalMem);
  408.         return (HA_SUBSCRIPT);              // subscript out of range
  409.      }
  410.  
  411.    // Open the file
  412.    hSaveFile = _lopen(FileSpec, OF_WRITE);
  413.    if(hSaveFile < 0)
  414.     {
  415.         LocalUnlock(hLocalMem);
  416.         return HA_FILEOPENERROR;
  417.     }
  418.  
  419.    for(element = 0L; element < nelements; element++)
  420.     {
  421.  
  422.       // calculate pointer to element
  423.       ptr = (BYTE _huge *) GlobalLock(pArray -> handle);
  424.       ptr = ptr + element * pArray->recsize;
  425.  
  426.       // Write out the record
  427.       if(_lwrite(hSaveFile, ptr, OutLen) < 0)
  428.        {
  429.          GlobalUnlock(pArray -> handle);
  430.          LocalUnlock(hLocalMem);
  431.          _lclose(hSaveFile);
  432.          return HA_FILEWRITEERROR;
  433.        }
  434.  
  435.       GlobalUnlock(pArray -> handle);
  436.  
  437.     }
  438.  
  439.    // Wrap up and return
  440.    _lclose(hSaveFile);
  441.  
  442.    LocalUnlock(hLocalMem);
  443.    return(element);
  444.  
  445.  }
  446.  
  447. /********************************************************************
  448. *   HugeLoad - Loads a Huge Array from the specified file           *
  449. *              Returns the number of elements loaded                *
  450. *                                                                   *
  451. *   NB!  The array must have been allocated and be of sufficient    *
  452. *   NB!  size to hold the array.                                    *
  453. ********************************************************************/
  454. long FAR pascal HugeLoad(int hArray, int InLen, LPSTR FileSpec)
  455.  {
  456.    int                 BytesRead;          // number of bytes read from the file
  457.    int                 hLoadFile;          // handle to the save file
  458.    BYTE _huge          *ptr;               // pointer to array element
  459.    long                element;            // element in the huge array
  460.    pDescrip            pArray;             // pointer to array descriptor
  461.  
  462.    if (hArray < 0 || hArray >= NumArrays)
  463.        return (HA_BADARRAY);               // illegal array handle
  464.  
  465.    pArray = (pDescrip) LocalLock(hLocalMem) + hArray;
  466.  
  467.    if (pArray -> handle == NULL)
  468.     {
  469.        LocalUnlock(hLocalMem);
  470.        return (HA_BADARRAY);               // array hasn't been allocated yet
  471.     }
  472.  
  473.    // Open the file
  474.    if((hLoadFile = _lopen(FileSpec, OF_READ)) < 0)
  475.     {
  476.         LocalUnlock(hLocalMem);
  477.         return HA_FILEOPENERROR;
  478.     }
  479.  
  480.    for(element = 0L; element < pArray -> ubound ; element++)
  481.     {
  482.  
  483.       // calculate pointer to element
  484.       ptr = (BYTE _huge *) GlobalLock(pArray -> handle);
  485.       ptr = ptr + element * pArray->recsize;
  486.  
  487.       // Read the record
  488.       BytesRead = _lread(hLoadFile, ptr, InLen);
  489.       if(BytesRead < 0)
  490.        {
  491.          GlobalUnlock(pArray -> handle);
  492.          LocalUnlock(hLocalMem);
  493.          _lclose(hLoadFile);
  494.          return HA_FILEREADERROR;
  495.        }
  496.       if(BytesRead == 0)
  497.        {
  498.          GlobalUnlock(pArray -> handle);
  499.          break;
  500.        }
  501.  
  502.       GlobalUnlock(pArray -> handle);
  503.  
  504.     }
  505.  
  506.    // Wrap up and return
  507.    _lclose(hLoadFile);
  508.  
  509.    LocalUnlock(hLocalMem);
  510.    return(element);
  511.  
  512.  }
  513.